<template>
    <div class="person">
        姓：<input type="text" v-model="lastName"/><br/>
        名：<input type="test" v-model="firstName"/><br/>
        全名：<span>{{ fullName }}</span><br/>
        全名：<span>{{ setableFullName }}</span><br/>
        <button @click="changeName">修改全面</button>
    </div>
</template>

<script lang="ts" setup name="Person">
    import { computed, ref } from 'vue';

    let lastName = ref('zhang');
    let firstName = ref('san');

    /* 计算属性：当计算属性所依赖的外部值发生变化，它就会重新调用函数来算一遍，然后把值保存起来，如果下次调用计算属性时，
       其所依赖的外部值没有变化，它就会直接把之前的计算结果拿来用，而不是再调用一遍方法。有些类似于懒加载。

       值得注意的是，计算属性所依赖的外部属性必须是响应式的，否则无法追踪其变化。

       计算属性有两种类型：只读、可读可写 */

    // 只读的计算属性（不能写 fullName = 'new name'）。 
    let fullName = computed(() => {
        return lastName.value.slice(0,1).toUpperCase() + lastName.value.slice(1) + '-' + firstName.value;
    });

    // 可读可写的计算属性（设置getter和setter）
    let setableFullName = computed({
        get() {
            return lastName.value.slice(0,1).toUpperCase() + lastName.value.slice(1) + '-' + firstName.value;
        },
        set(val) {
            const [str1, str2] = val.split('-');
            lastName.value = str1;
            firstName.value = str2;
        }
    });

    function changeName() {
        // fullName = 'new name';          // 错误
        // fullName.value = 'new name';    // 错误
        setableFullName.value = 'li-si';    // 这里实际会调用setableFullName的set方法，入参为li-si
    }
</script>

<style scoped>
    .person {
        background-color: skyblue;
        box-shadow: 0 0 10px;
        border-radius: 10px;
        padding:20px
    }
    button {
        margin: 0 5px;
    }
</style>